package itpenguin;

import itpenguin.common.PageInfo;
import itpenguin.common.Util;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheException;
import net.sf.jsr107cache.CacheFactory;
import net.sf.jsr107cache.CacheManager;

/**
 * Cache controler
 * @author hiro
 *
 */
public class FlipperFilter implements Filter {

	private static Cache cache;
	
	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		final StringWriter sw = new StringWriter();
		HttpServletResponse resp = (HttpServletResponse)response;
		HttpServletRequest req = (HttpServletRequest)request;
		String cacheKey = null;
		
		if (req.getServletPath().equals("/")) {
			cacheKey = "top";
			resp.setHeader("Cache-Control", "max-age=86400");
		} else {
			String[] key = Util.GetKey(req);
			if (key == null)
			{
				resp.sendError(HttpServletResponse.SC_NOT_FOUND);
				return;
			}
			
			if (req.getServletPath().equals("/articles")) {
				if (key.length == 1) {
					cacheKey = key[0] + "1";
				} else {
					cacheKey = key[0] + key[1];
				}
			} else {
				cacheKey = key[0];
			}
			resp.setHeader("Cache-Control", "max-age=604800");
		}
		resp.addDateHeader("Date", (new Date()).getTime());
		
		if (cache.containsKey(cacheKey)){
			PageInfo page = (PageInfo)cache.get(cacheKey);
			resp.setCharacterEncoding("UTF-8");
			resp.setHeader("Content-Type","text/html; charset=utf-8");
			resp.addDateHeader("Last-Modified", page.published);
			PrintWriter out = response.getWriter();
			out.write(page.content);
		} else {
			final LongHolder published = new LongHolder();
			ServletResponse wrapRes 
			= new HttpServletResponseWrapper(resp)
			{
	
				@Override
				public ServletOutputStream getOutputStream() throws IOException {
					return new ServletOutputStream() {
			            @Override
			            public void write(int b) throws IOException {
			            }
			        };
	
				}
	
				@Override
				public PrintWriter getWriter() throws IOException {
					 return new PrintWriter(sw);
				}

				@Override
				public void addDateHeader(String name, long date) {
					published.value = date;
				}
				
			};
			
			chain.doFilter(req, wrapRes);
			
			if (!response.isCommitted()) {
				PageInfo page = new PageInfo();
				page.content = sw.toString();
				page.published = published.value;
				resp.addDateHeader("Last-Modified", published.value);
				cache.put(cacheKey, page); 
				PrintWriter out = response.getWriter();
				out.write(page.content);
			}
		}
		
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		Map<String, Object> props = new HashMap<String, Object>();
//		props.put(GCacheFactory.EXPIRATION_DELTA, 86400);
		try {
			CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
			cache = cacheFactory.createCache(props);
		} catch (CacheException e) {
			throw new ServletException(e);
		}
	}
	
	private class LongHolder
	{
		public long value;
	}
	
	public static void clearCache(String id) {
		cache.remove(id);
	}

	public static void clearCache() {
		cache.clear();
	}
}
